
package arffreader;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.HashMap;
import java.util.logging.Level;
import java.util.logging.Logger;

public class BufferedReaderArff extends BufferedReader{

    private boolean inData = false;
    private HashMap<String, Integer> hashTable;
    private HashMap<Integer, String> hashInversa;
    private HashMap<Integer, String> hashTipos;
    private String vstrings[] = null;

    public BufferedReaderArff(FileReader fr)
    {
        super(fr);
        hashTable = new HashMap<String, Integer>();
        hashInversa = new HashMap<Integer, String>();
        hashTipos = new HashMap<Integer, String>();
        inData = false;
        try
        {
            readHeader();
        } 
        catch (Exception ex)
        {
            Logger.getLogger(BufferedReaderArff.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    /**
     * Mueve el cursor del fichero hasta la sección de datos
     */
    private boolean GoData() throws Exception
    {
        if (this == null)
        {
            throw (new Exception());
        }
        if (this.inData == true)
        {
            throw (new Exception());
        }
        String linea;
        while((linea = this.readLine()) != null)
        {
            if (linea.contains("@DATA")||linea.contains("@data"))
            {
                inData = true;
                return true;
            }
        }
        return false;
    }

    /**
     * Crea una HashTable con el nombre del atributo como clave y
     * la posición de la instancia en la que se encuentra
     * @throws Exception
     */
    private void readHeader() throws Exception
    {
        int i = 0;
        if (this == null)
        {
            throw (new Exception());
        }
        if (this.inData == true)
        {
            throw (new Exception());
        }
        String linea;
        while((linea = this.readLine()) != null)
        {
            if (linea.contains("@DATA")||linea.contains("@data"))
            {
                inData = true;
                return;
            }
            if (linea.contains("@ATTRIBUTE")||linea.contains("@attribute"))
            {
                vstrings = linea.split(" ");
                hashTable.put(vstrings[1], i);
                hashInversa.put(i, vstrings[1]);
                hashTipos.put(i, vstrings[2]);
                i++;
            }
        }
    }
    
    public boolean containsAttr(String attr){
        return hashTable.containsKey(attr);
    }

    public int getPosAttr(String attr)
    {
        Object pos;
        pos  = hashTable.get(attr);
        return ((Integer)pos).intValue();
    }
    
    public String getAttrPos(int attr)
    {
        Object pos;
        pos  = hashInversa.get(attr);
        return ((String)pos).toString();
    }

    String getAttrTipoPos(int attr) {
        Object pos;
        pos  = hashTipos.get(attr);
        return ((String)pos).toString();
    }
    public String readLineAttr(String attr)
    {
        String linea;
        int posAttr;
        try
        {
            if ((linea = this.readLine()) != null)
            {
                vstrings = linea.split(",");
                posAttr = getPosAttr(attr);
                return vstrings[posAttr];
            }
            else
            {
                return null;
            }
        }
        catch (IOException ex)
        {
            Logger.getLogger(BufferedReaderArff.class.getName()).log(Level.SEVERE, null, ex);
            return null;
        }
    }

    public String readLineAttr(int attr)
    {
        String linea;
        int posAttr;
        try
        {
            if ((linea = this.readLine()) != null)
            {
                vstrings = linea.split(",");
                posAttr = attr;
                return vstrings[posAttr];
            }
            else
            {
                return null;
            }
        }
        catch (IOException ex)
        {
            Logger.getLogger(BufferedReaderArff.class.getName()).log(Level.SEVERE, null, ex);
            return null;
        }
    }
    /**
     * @param attrNom nombre del atributo
     * @param attrVal valor del atributo con el nombre dado
     * @return Como readLine devuelve una linea. Enn este caso la linea se corresponde 
     *          con las que el atributo attrNom tienr valor attrVal 
     */
    public String readLine(String attrNom, String attrVal){
        String linea;
        int posAttr;
        try
        {
            while ((linea = this.readLine()) != null)
            {
                vstrings = linea.split(",");
                posAttr = getPosAttr(attrNom);
                if( vstrings[posAttr].contains(attrVal)){
                   break;
                }
            }
            return linea;
        }
        catch (IOException ex)
        {
            Logger.getLogger(BufferedReaderArff.class.getName()).log(Level.SEVERE, null, ex);
            return null;
        }
    }


}
